<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务，帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件，不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\admin\model;

use app\common\model\User as UserModel;
use app\admin\model\UserOauth as UserOauthModel;
use app\admin\model\user\GradeLog as GradeLogModel;
use app\admin\model\user\PointsLog as PointsLogModel;
use app\admin\model\user\WalletLog as WalletLogModel;
use app\admin\model\user\BalanceLog as BalanceLogModel;
use app\admin\service\store\User as StoreUserService;
use app\admin\model\Zone as ZoneModel;
use app\common\enum\user\balanceLog\Scene as SceneEnum;
use app\common\enum\user\grade\log\ChangeType as ChangeTypeEnum;
use app\common\library\helper;

/**
 * 用户模型
 * Class User
 * @package app\store\model
 */
class User extends UserModel
{
    // 充值类型枚举: 余额
    const RECHARGE_TYPE_BALANCE = 'balance';

    // 充值类型枚举: 积分
    const RECHARGE_TYPE_POINTS = 'points';

    // 充值类型枚举: 个人钱包
    const RECHARGE_TYPE_WALLET = 'wallet';
    /**
     * 获取当前用户总数
     * @param array $param 查询参数
     * @return int|string
     */
    public function getUserTotal(array $param = [])
    {
        // 检索查询条件
        $filter = $this->getUserTotalFilter($param);
        // 查询结果
        return $this->where($filter)
            ->where('is_delete', '=', '0')
            ->count();
    }

    /**
     * 获取当前用户总数的查询条件
     * @param array $param
     * @return array
     */
    private function getUserTotalFilter(array $param = []): array
    {
        // 默认查询参数
        $params = $this->setQueryDefaultValue($param, [
            'date' => null,         // 注册日期 如: 2020-08-01
            'isConsume' => null,    // 是否已消费
        ]);
        // 检索查询条件
        $filter = [];
        if (!is_null($params['date'])) {
            $startTime = strtotime($params['date']);
            $filter[] = ['create_time', '>=', $startTime];
            $filter[] = ['create_time', '<', $startTime + 86400];
        }
        if (is_bool($params['isConsume'])) {
            $filter[] = ['pay_money', $params['isConsume'] ? '>' : '=', 0];
        }
        return $filter;
    }

    /**
     * 获取用户列表
     * @param array $param
     * @return \think\Paginator
     * @throws \think\db\exception\DbException
     */
    public function getList(array $param = []): \think\Paginator
    {

        // 检索查询条件
        $filter = $this->getFilter($param);
        // 获取用户列表
        $users = $this->with(['avatar', 'grade','zone'])
            ->where($filter)
            ->where('is_delete', '=', '0')
            ->order(['create_time' => 'desc'])
            ->paginate(15);

        // 处理用户列表，为每个用户添加完整的部门路径
        foreach ($users as &$user) {
            if ($user->status == 0) {
                $user->zt = "未激活";
            } else {
                $user->zt = "已激活";
            }
            $user->zonePath = "";
            if ($user->zone_id) {

                // 假设我们使用getParentDepts来获取部门路径
                $zonePath = (new ZoneModel())->getParentZones($user->zone_id);

                if(!empty($zonePath)){
                    foreach ($zonePath as $v){
                        if($user->zonePath == ""){
                            $user->zonePath = $v->name;
                        }else{
                            $user->zonePath = $user->zonePath . "- ".$v->name;
                        }

                    }
                }
               // $user->zonePath = array_column($zonePath, 'name'); // 假设我们只关心部门名称
            }
        }
        return $users;
    }

    /**
     * 获取查询条件
     * @param array $param
     * @return array
     */
    private function getFilter(array $param = []): array
    {
        // 默认查询条件
        $params = $this->setQueryDefaultValue($param, [
            'search' => '',     // 会员昵称
            'gender' => -1,     // 用户性别
            'gradeId' => 0,       // 用户等级
        ]);
        // 检索查询条件
        $filter = [];
        // 会员昵称
        if(isset($params['searchType']) && $params['searchType'] == 10){
            !empty($params['searchValue']) && $filter[] = ['mobile', 'like', "%{$params['searchValue']}%"];
        }
        if(isset($params['searchType']) && $params['searchType']  == 20){
            !empty($params['searchValue']) && $filter[] = ['name', 'like', "%{$params['searchValue']}%"];
        }
       // 用户所在区
        if(isset($params['zone_id']) && $params['zone_id'] > 0){
            $filter[] = ['zone_id', '=', (int)$params['zone_id']];
        }
        // 用户状态
        if(isset($params['status'])){
            $params['status'] >= 0 && $filter[] = ['status', '=', (int)$params['status']];
        }
        // 起止时间
        if (!empty($params['betweenTime'])) {
            $times = between_time($params['betweenTime']);
            $filter[] = ['create_time', '>=', $times['start_time']];
            $filter[] = ['create_time', '<', $times['end_time'] + 86400];
        }
        return $filter;
    }

    /**
     * 激活用户
     * @return false|mixed
     */
    public function setActive()
    {
        return $this->transaction(function () {
            // 将第三方用户信息记录标记删除
            UserOauthModel::updateBase(['status' => 1], [
                ['user_id', '=', $this['user_id']]
            ]);
            // 标记为已删除
            return $this->save(['status' => 1]);
        });
    }



    /**
     * 冻结用户
     * @return false|mixed
     */
    public function setCancel()
    {
        return $this->transaction(function () {
            // 将第三方用户信息记录标记删除
            UserOauthModel::updateBase(['status' => 0], [
                ['user_id', '=', $this['user_id']]
            ]);
            // 标记为已删除
            return $this->save(['status' => 0]);
        });
    }
    /**
     * 删除用户
     * @return false|mixed
     */
    public function setDelete()
    {
        return $this->transaction(function () {
            // 将第三方用户信息记录标记删除
            UserOauthModel::updateBase(['is_delete' => 1], [
                ['user_id', '=', $this['user_id']]
            ]);
            // 标记为已删除
            return $this->save(['is_delete' => 1]);
        });
    }

    /**
     * 用户充值
     * @param string $target 充值类型
     * @param array $data 表单数据
     * @return bool
     */
    public function recharge(string $target, array $data): bool
    {
        // 当前操作人用户名
        $storeUserName = StoreUserService::getLoginInfo()['user']['user_name'];
        if ($target === self::RECHARGE_TYPE_BALANCE) {
            return $this->rechargeToBalance($storeUserName, $data['balance']);
        } elseif ($target === self::RECHARGE_TYPE_POINTS) {
            return $this->rechargeToPoints($storeUserName, $data['points']);
        }
        elseif ($target === self::RECHARGE_TYPE_WALLET) {
            return $this->rechargeToWallet($storeUserName, $data['wallet']);
        }
        return false;
    }

    /**
     * 用户充值：余额
     * @param string $storeUserName
     * @param array $data
     * @return bool
     */
    private function rechargeToBalance(string $storeUserName, array $data): bool
    {
        if (!isset($data['money']) || $data['money'] === '' || $data['money'] < 0) {
            $this->error = '请输入正确的金额';
            return false;
        }

        // 判断充值方式，计算最终金额
        if ($data['mode'] === 'inc') {
            $diffMoney = $data['money'];
            if($this['balance'] >= 400){
                $this->error = '充值的金额不能大于400元，请重新检查';
                return false;
            }
        } elseif ($data['mode'] === 'dec') {
            $diffMoney = -$data['money'];
        } else {
            $diffMoney = helper::bcsub($data['money'], $this['balance']);
        }
        // 更新记录
        $this->transaction(function () use ($storeUserName, $data, $diffMoney) {
            // 更新账户余额
            static::setIncBalance((int)$this['user_id'], (float)$diffMoney);
            // 新增余额变动记录
            BalanceLogModel::add(SceneEnum::ADMIN, [
                'user_id' => $this['user_id'],
                'money' => (float)$diffMoney,
                'remark' => $data['remark'],
            ], [$storeUserName]);
        });
        return true;
    }

    /**
     * 用户充值：积分
     * @param string $storeUserName
     * @param array $data
     * @return bool
     */
    private function rechargeToPoints(string $storeUserName, array $data): bool
    {
        if (!isset($data['value']) || $data['value'] === '' || $data['value'] < 0) {
            $this->error = '请输入正确的积分数量';
            return false;
        }
        // 判断充值方式，计算最终积分
        if ($data['mode'] === 'inc') {
            $diffMoney = $data['value'];
        } elseif ($data['mode'] === 'dec') {
            $diffMoney = -$data['value'];
        } else {
            $diffMoney = $data['value'] - $this['points'];
        }
        // 更新记录
        $this->transaction(function () use ($storeUserName, $data, $diffMoney) {
            // 更新账户积分
            $this->setInc($this['user_id'], 'points', $diffMoney);
            // 新增积分变动记录
            PointsLogModel::add([
                'user_id' => $this['user_id'],
                'value' => $diffMoney,
                'describe' => "后台管理员 [{$storeUserName}] 操作",
                'remark' => $data['remark'],
            ]);
        });
        return true;
    }

    /**
     * 用户充值：个人钱包
     * @param string $storeUserName
     * @param array $data
     * @return bool
     */
    private function rechargeToWallet(string $storeUserName, array $data): bool
    {
        if (!isset($data['value']) || $data['value'] === '' || $data['value'] < 0) {
            $this->error = '请输入正确的金额数量';
            return false;
        }
        // 判断充值方式，计算最终积分
        if ($data['mode'] === 'inc') {
            $diffMoney = $data['value'];
        } elseif ($data['mode'] === 'dec') {
            $diffMoney = -$data['value'];
        } else {
            $diffMoney = $data['value'] - $this['wallet'];
        }
        // 更新记录
        $this->transaction(function () use ($storeUserName, $data, $diffMoney) {
            // 更新账户积分
            $this->setInc($this['user_id'], 'wallet', $diffMoney);
            // 新增积分变动记录
            WalletLogModel::add([
                'user_id' => $this['user_id'],
                'money' => $diffMoney,
                'scene' => 30,
                'admin_id' => 2,
                'describe' => "后台管理员 [{$storeUserName}] 操作",
                'remark' => $data['remark'],
            ]);
        });
        return true;
    }

    /**
     * 修改用户等级
     * @param array $data
     * @return mixed
     */
    public function updateGrade(array $data)
    {
        // 变更前的等级id
        $oldGradeId = $this['grade_id'];
        return $this->transaction(function () use ($oldGradeId, $data) {
            // 更新用户的等级
            $status = $this->save(['grade_id' => $data['grade_id']]);
            // 新增用户等级修改记录
            if ($status) {
                (new GradeLogModel)->record([
                    'user_id' => $this['user_id'],
                    'old_grade_id' => $oldGradeId,
                    'new_grade_id' => $data['grade_id'],
                    'change_type' => ChangeTypeEnum::ADMIN_USER,
                    'remark' => $data['remark']
                ]);
            }
            return $status !== false;
        });
    }

    /**
     * 修改用户信息
     * @return false|mixed
     */
    public function updateInfo(array $data)
    {
        return $this->save(['mobile' =>$data['mobile'],'name'=>$data['name'],'zone_id' => $data['zone_id']]);
    }

    /**
     * 消减用户的实际消费金额
     * @param int $userId
     * @param float $expendMoney
     * @return mixed
     */
    public function setDecUserExpend(int $userId, float $expendMoney)
    {
        return $this->setDec(['user_id' => $userId], 'expend_money', $expendMoney);
    }
}
